home *** CD-ROM | disk | FTP | other *** search
- /* DBAZ.C
- * Contributed to Public Domain 9/93
- * by Thad Smith, Boulder Co.
- */
- #include <stdlib.h>
- #include <string.h>
- #include "baz.h"
- #include "bazcom.h"
- #include "crc16.h"
-
- #define LAST_CODE (FIRST_CODE + BASE -1)
- #define BASESQ (unsigned long)(BASE*BASE)
- #define BASEVAL(c) (unsigned)((c)-FIRST_CODE)
- #define ISENCODE(c) ((c) >= FIRST_CODE && \
- (c) <= LAST_CODE)
-
- static unsigned int crc;/* input file CRC */
- static size_t n_unused; /* # unused input bytes */
- static int ninb; /* # bytes in inbuf */
- static int done; /* set if finished */
- static char inbuf[ENCB_LEN * 2 + 2];
- static unsigned char outbuf[BINB_LEN * 2];
- static int (*outfunc) (const char *out, size_t len);
-
- static decode_stat
- decode_endmark(const char *data, size_t len);
-
- /* Initialize the BAZ911 decoder. */
- int dbaz_init (outf_t *p_outfunc) {
- initcrctab ();
- crc = CRC_INIT_VALUE;
- done = 0;
- ninb = 0;
- n_unused = 0;
- outfunc = p_outfunc;
- return 0;
- }
-
- /* Decode block of data. */
- decode_stat
- dbaz_data (const unsigned char *data, size_t len) {
- int s; /* output return status */
-
- if (done) {
- n_unused += len;
- return DECR_END;
- } else if (len == 0)
- return DECR_NO_ENDMARK;
-
- for (;;) {
- /* fill block input buffer */
- while (ninb < ENCB_LEN) {
- if (ISENCODE(*data))
- inbuf[ninb++] = (char) *data;
- data++;
- if (--len == 0)
- return DECR_OK;
-
- }
- if (*inbuf == END_FLAG) {
- return decode_endmark ((const char *) data,
- len );
- }
- if (decode_11_to_9 (outbuf, inbuf))
- return DECR_INVALID_DATA;
- ninb = 0;
- crc = updcrc (crc, outbuf, BINB_LEN);
- if ((s= outfunc ((char *)outbuf,BINB_LEN)) != 0)
- return (decode_stat) s;
- }
- }
-
- /* Return number of characters in internal buffer.
- * This can be used after DECR_END status is returned
- * to determine the number of unused characters given
- * to the decoder. */
- size_t dbaz_excess_chars (void) {
- return n_unused;
- }
-
- decode_stat decode_endmark (
- const char *data, /* data following inbuf */
- size_t len /* length of data */
- )
- {
- int s; /* output return status */
- int nreq; /* # input bytes required for
- * end ensemble */
- unsigned int rc; /* # remaining data bytes */
-
- if ((rc = BASEVAL(inbuf[1])) > MAX_ENDBLK_DB)
- return DECR_INVALID_DATA;
-
- memset (inbuf+ninb, FIRST_CODE, 2*ENCB_LEN+2-ninb);
- nreq = rc +4 +CRCLBY;
- if (nreq < ENCB_LEN)
- nreq = ENCB_LEN; /* min size is 1 block */
- if (rc > BINB_LEN - CRCLBY)
- nreq += 2; /* use part of 2nd blk */
- /* get remaining characters */
- while (ninb < nreq) {
- if (len == 0)
- return DECR_OK; /* need more input chars */
- if (ISENCODE(*data))
- inbuf[ninb++] = *data;
- data++;
- len--;
- }
- done = 1;
- if (decode_11_to_9 (outbuf, inbuf+2))
- return DECR_INVALID_DATA;
- if (rc > BINB_LEN - CRCLBY) {
- if (decode_11_to_9 (outbuf+BINB_LEN,
- inbuf+2+ENCB_LEN))
- return DECR_INVALID_DATA;
- }
- crc = updcrc (crc, outbuf, rc);
- if ((s = outfunc ((char *) outbuf, rc)) != 0)
-
- return (decode_stat) s;
- if (((crc >> 8) & 0xff) != outbuf[rc] ||
- ( crc & 0xff) != outbuf[rc+1] )
- return DECR_CRC_ERR;
- n_unused = len;
- return DECR_END;
- }
-
- /* Decode 11 printable ASCII characters into 9 bytes */
- int /* return: 0=OK, 1= invalid input */
- decode_11_to_9 (unsigned char out[], const char in[]) {
- unsigned long block;
- unsigned b2, q1, q2, i;
-
- block = BASEVAL(in[0]) * BASESQ +
- (BASEVAL(in[1]) * BASE + BASEVAL(in[2]));
- out[0] = (unsigned) block & 0xff;
- b2 = (unsigned) (block >> 8);
- q1 = b2 / PBASE;
- q2 = b2 - q1 * PBASE;
- if (q1 >= PBASE) return 1;
-
- for (i = 1; i < 9; i += 4) {
- block = (BASEVAL(in[i+2]) * BASE +
- BASEVAL(in[i+3])) * BASESQ +
- (BASEVAL(in[i+4]) * BASE + BASEVAL(in[i+5]));
-
- if (((unsigned)(block >> 16) >= PBMULT) ||
- q1 == PBASE-1 && block >
- (0xffffffffUL -(PBMULT*(PBASE-1UL) << 16))) {
- return 1;
- }
-
- block += (unsigned long) (q1 * PBMULT) << 16;
- out[i+0] = (unsigned char) (block >> 24);
- out[i+1] = (unsigned char) (block >> 16);
- out[i+2] = (unsigned char) (block >> 8);
- out[i+3] = (unsigned char) block;
- q1 = q2;
- }
- return 0;
- }
-
- /* End of File */
-
-